<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" integrity="sha256-mUZM63G8m73Mcidfrv5E+Y61y7a12O5mW4ezU3bxqW4=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"tallgy.gitee.io","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/js/config.js"></script>
<meta name="description" content="React 学习-核心概念 &#x2F; v17.0.2jsx属性值​        你可以通过使用引号，来将属性值指定为字符串字面量： 1const element &#x3D; &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;www.reactjs.org&quot;&gt; link &lt;&#x2F;a&gt;;  ​        也可以使用大括号，来在属性值中插入一个 JavaScript 表达式： 1cons">
<meta property="og:type" content="article">
<meta property="og:title" content="react学习-核心概念">
<meta property="og:url" content="http://tallgy.gitee.io/2022/02/14/React/react%E5%AD%A6%E4%B9%A0-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5/index.html">
<meta property="og:site_name" content="tallgy&#39;s blog">
<meta property="og:description" content="React 学习-核心概念 &#x2F; v17.0.2jsx属性值​        你可以通过使用引号，来将属性值指定为字符串字面量： 1const element &#x3D; &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;www.reactjs.org&quot;&gt; link &lt;&#x2F;a&gt;;  ​        也可以使用大括号，来在属性值中插入一个 JavaScript 表达式： 1cons">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2022-02-14T11:30:54.000Z">
<meta property="article:modified_time" content="2023-06-25T08:57:29.323Z">
<meta property="article:author" content="tallgy">
<meta property="article:tag" content="React">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://tallgy.gitee.io/2022/02/14/React/react%E5%AD%A6%E4%B9%A0-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://tallgy.gitee.io/2022/02/14/React/react%E5%AD%A6%E4%B9%A0-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5/","path":"2022/02/14/React/react学习-核心概念/","title":"react学习-核心概念"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>react学习-核心概念 | tallgy's blog</title>
  




  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">tallgy's blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>







</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#React-%E5%AD%A6%E4%B9%A0-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5-v17-0-2"><span class="nav-number">1.</span> <span class="nav-text">React 学习-核心概念 &#x2F; v17.0.2</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#jsx"><span class="nav-number">1.1.</span> <span class="nav-text">jsx</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B1%9E%E6%80%A7%E5%80%BC"><span class="nav-number">1.1.1.</span> <span class="nav-text">属性值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jsx%E8%A1%A8%E7%A4%BA%E5%AF%B9%E8%B1%A1"><span class="nav-number">1.1.2.</span> <span class="nav-text">jsx表示对象</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%83%E7%B4%A0%E6%B8%B2%E6%9F%93"><span class="nav-number">1.2.</span> <span class="nav-text">元素渲染</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9B%B4%E6%96%B0%E5%B7%B2%E6%B8%B2%E6%9F%93%E7%9A%84%E5%85%83%E7%B4%A0"><span class="nav-number">1.2.1.</span> <span class="nav-text">更新已渲染的元素</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#React-%E5%8F%AA%E6%9B%B4%E6%96%B0%E5%AE%83%E9%9C%80%E8%A6%81%E6%9B%B4%E6%96%B0%E7%9A%84%E9%83%A8%E5%88%86"><span class="nav-number">1.2.2.</span> <span class="nav-text">React 只更新它需要更新的部分</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6-amp-amp-props"><span class="nav-number">1.3.</span> <span class="nav-text">组件 &amp;&amp; props</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E7%BB%84%E4%BB%B6%E4%B8%8E-class-%E7%BB%84%E4%BB%B6"><span class="nav-number">1.3.1.</span> <span class="nav-text">函数组件与 class 组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%B8%B2%E6%9F%93%E7%BB%84%E4%BB%B6"><span class="nav-number">1.3.2.</span> <span class="nav-text">渲染组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%84%E5%90%88%E7%BB%84%E4%BB%B6"><span class="nav-number">1.3.3.</span> <span class="nav-text">组合组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Props%E7%9A%84%E5%8F%AA%E8%AF%BB%E6%80%A7"><span class="nav-number">1.3.4.</span> <span class="nav-text">Props的只读性</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#State-amp-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">1.4.</span> <span class="nav-text">State &amp; 生命周期</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B0%86%E5%87%BD%E6%95%B0%E7%BB%84%E4%BB%B6%E8%BD%AC%E6%8D%A2%E4%B8%BAclass%E7%BB%84%E4%BB%B6"><span class="nav-number">1.4.1.</span> <span class="nav-text">将函数组件转换为class组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%91-class-%E7%BB%84%E4%BB%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%B1%80%E9%83%A8%E7%9A%84-state"><span class="nav-number">1.4.2.</span> <span class="nav-text">向 class 组件中添加局部的 state</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%96%B9%E6%B3%95%E6%B7%BB%E5%8A%A0%E5%88%B0-Class-%E4%B8%AD"><span class="nav-number">1.4.3.</span> <span class="nav-text">生命周期方法添加到 Class 中</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%96%B9%E6%B3%95"><span class="nav-number">1.4.3.1.</span> <span class="nav-text">生命周期方法</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA-clock-%E7%BB%84%E4%BB%B6"><span class="nav-number">1.4.3.1.1.</span> <span class="nav-text">创建 clock 组件</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E8%B0%83%E7%94%A8%E9%A1%BA%E5%BA%8F"><span class="nav-number">1.4.3.1.2.</span> <span class="nav-text">调用顺序</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%AD%A3%E7%A1%AE%E7%9A%84%E4%BF%AE%E6%94%B9-State"><span class="nav-number">1.4.4.</span> <span class="nav-text">正确的修改 State</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%8D%E8%A6%81%E7%9B%B4%E6%8E%A5%E4%BF%AE%E6%94%B9state%E9%87%8C%E9%9D%A2%E7%9A%84%E5%B1%9E%E6%80%A7"><span class="nav-number">1.4.4.1.</span> <span class="nav-text">不要直接修改state里面的属性</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#state%E6%9B%B4%E6%96%B0%E5%8F%AF%E8%83%BD%E6%98%AF%E5%BC%82%E6%AD%A5%E7%9A%84"><span class="nav-number">1.4.4.2.</span> <span class="nav-text">state更新可能是异步的</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#State-%E7%9A%84%E6%9B%B4%E6%96%B0%E4%BC%9A%E8%A2%AB%E5%90%88%E5%B9%B6"><span class="nav-number">1.4.4.3.</span> <span class="nav-text">State 的更新会被合并</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%98%AF%E5%90%91%E4%B8%8B%E6%B5%81%E5%8A%A8%E7%9A%84"><span class="nav-number">1.4.5.</span> <span class="nav-text">数据是向下流动的</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86"><span class="nav-number">1.5.</span> <span class="nav-text">事件处理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%91%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E7%A8%8B%E5%BA%8F%E4%BC%A0%E9%80%92%E5%8F%82%E6%95%B0"><span class="nav-number">1.5.1.</span> <span class="nav-text">向事件处理程序传递参数</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9D%A1%E4%BB%B6%E6%B8%B2%E6%9F%93"><span class="nav-number">1.6.</span> <span class="nav-text">条件渲染</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link"><span class="nav-number">2.</span> <span class="nav-text">
        Welcome
      </span></a></li><li class="nav-item nav-level-1"><a class="nav-link"><span class="nav-number">3.</span> <span class="nav-text">
        {props.title}
      </span></a></li><li class="nav-item nav-level-1"><a class="nav-link"><span class="nav-number">4.</span> <span class="nav-text">Shopping List for {this.props.name}</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">tallgy</p>
  <div class="site-description" itemprop="description">只是一个知识的搬运工</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">107</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">32</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">74</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/14/React/react%E5%AD%A6%E4%B9%A0-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          react学习-核心概念
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-14 19:30:54" itemprop="dateCreated datePublished" datetime="2022-02-14T19:30:54+08:00">2022-02-14</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/React/" itemprop="url" rel="index"><span itemprop="name">React</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h1 id="React-学习-核心概念-v17-0-2"><a href="#React-学习-核心概念-v17-0-2" class="headerlink" title="React 学习-核心概念 / v17.0.2"></a>React 学习-核心概念 / v17.0.2</h1><h2 id="jsx"><a href="#jsx" class="headerlink" title="jsx"></a>jsx</h2><h3 id="属性值"><a href="#属性值" class="headerlink" title="属性值"></a>属性值</h3><p>​        你可以通过使用引号，来将属性值指定为字符串字面量：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const element = &lt;a href=&quot;https://www.reactjs.org&quot;&gt; link &lt;/a&gt;;</span><br></pre></td></tr></table></figure>

<p>​        也可以使用大括号，来在属性值中插入一个 JavaScript 表达式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const element = &lt;img src=&#123;user.avatarUrl&#125;&gt;&lt;/img&gt;;</span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>警告：</strong></p>
<p>因为 JSX 语法上更接近 JavaScript 而不是 HTML，所以 React DOM 使用 <code>camelCase</code>（小驼峰命名）来定义属性的名称，而不使用 HTML 属性名称的命名约定。</p>
<p>例如，JSX 里的 <code>class</code> 变成了 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/className"><code>className</code></a>，而 <code>tabindex</code> 则变为 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/tabIndex"><code>tabIndex</code></a>。</p>
</blockquote>
<h3 id="jsx表示对象"><a href="#jsx表示对象" class="headerlink" title="jsx表示对象"></a>jsx表示对象</h3><p>babel会把jsx转移为一个 React.createElement的函数调用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">const element = (</span><br><span class="line">  &lt;h1 className=&quot;greeting&quot;&gt;</span><br><span class="line">    Hello, world!</span><br><span class="line">  &lt;/h1&gt;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">const element = React.createElement(</span><br><span class="line">  &#x27;h1&#x27;,</span><br><span class="line">  &#123;className: &#x27;greeting&#x27;&#125;,</span><br><span class="line">  &#x27;Hello, world!&#x27;</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">这个是创建的对象的简化结构</span><br><span class="line">// 注意：这是简化过的结构</span><br><span class="line">const element = &#123;</span><br><span class="line">  type: &#x27;h1&#x27;,</span><br><span class="line">  props: &#123;</span><br><span class="line">    className: &#x27;greeting&#x27;,</span><br><span class="line">    children: &#x27;Hello, world!&#x27;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h2 id="元素渲染"><a href="#元素渲染" class="headerlink" title="元素渲染"></a>元素渲染</h2><h3 id="更新已渲染的元素"><a href="#更新已渲染的元素" class="headerlink" title="更新已渲染的元素"></a>更新已渲染的元素</h3><p>​        React 元素是<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Immutable_object">不可变对象</a>。一旦被创建，你就无法更改它的子元素或者属性。一个元素就像电影的单帧：它代表了某个特定时刻的 UI。</p>
<p>​        根据我们已有的知识，更新 UI 唯一的方式是创建一个全新的元素，并将其传入 <a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/docs/react-dom.html#render"><code>ReactDOM.render()</code></a>。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function tick() &#123;</span><br><span class="line">  const element = (</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">      &lt;h1&gt;Hello, world!&lt;/h1&gt;</span><br><span class="line">      &lt;h2&gt;It is &#123;new Date().toLocaleTimeString()&#125;.&lt;/h2&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  );</span><br><span class="line">  ReactDOM.render(element, document.getElementById(&#x27;root&#x27;));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">setInterval(tick, 1000);</span><br></pre></td></tr></table></figure>

<p>​        通过每秒调用 render来重新渲染</p>
<p><strong>注意：</strong></p>
<ul>
<li><p>在实践中，大多数 React 应用只会调用一次 <a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/docs/react-dom.html#render"><code>ReactDOM.render()</code></a>。在下一个章节，我们将学习如何将这些代码封装到<a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/docs/state-and-lifecycle.html">有状态组件</a>中。</p>
</li>
<li><p>我们建议你不要跳跃着阅读，因为每个话题都是紧密联系的。</p>
</li>
</ul>
<h3 id="React-只更新它需要更新的部分"><a href="#React-只更新它需要更新的部分" class="headerlink" title="React 只更新它需要更新的部分"></a>React 只更新它需要更新的部分</h3><p>​        React DOM 会将元素和它的子元素与它们之前的状态进行比较，并只会进行必要的更新来使 DOM 达到预期的状态。</p>
<p>​        就是说，我们虽然多次运行了 render，但是实际上只会更改必要的更新。</p>
<h2 id="组件-amp-amp-props"><a href="#组件-amp-amp-props" class="headerlink" title="组件 &amp;&amp; props"></a>组件 &amp;&amp; props</h2><h3 id="函数组件与-class-组件"><a href="#函数组件与-class-组件" class="headerlink" title="函数组件与 class 组件"></a>函数组件与 class 组件</h3><p>这两个组件是等效的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function Welcome(props) &#123;</span><br><span class="line">  return &lt;h1&gt;Hello, &#123;props.name&#125;&lt;/h1&gt;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class Welcome extends React.Component &#123;</span><br><span class="line">  render() &#123;</span><br><span class="line">    return &lt;h1&gt;Hello, &#123;this.props.name&#125;&lt;/h1&gt;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="渲染组件"><a href="#渲染组件" class="headerlink" title="渲染组件"></a>渲染组件</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">const element = &lt;div /&gt;;</span><br><span class="line"></span><br><span class="line">const element = &lt;Welcome name=&quot;Sara&quot; /&gt;;</span><br></pre></td></tr></table></figure>

<p>​        当 React 元素为用户自定义组件时，它会将 JSX 所接收的属性（attributes）以及子组件（children）转换为单个对象传递给组件，这个对象被称之为 “props”。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">function Welcome(props) &#123;</span><br><span class="line">  return &lt;h1&gt;Hello, &#123;props.name&#125;&lt;/h1&gt;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">这里传递的属性attributes 将会作为props对象里面的属性进行传递。class，className 都会使用props传递。</span><br><span class="line">const element = &lt;Welcome name=&quot;Sara&quot; /&gt;;</span><br><span class="line">ReactDOM.render(</span><br><span class="line">  element,</span><br><span class="line">  document.getElementById(&#x27;root&#x27;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<p><strong>注意：</strong> 组件名称必须以大写字母开头。</p>
<ul>
<li><p>React 会将以小写字母开头的组件视为原生 DOM 标签。例如，<code>&lt;div /&gt;</code> 代表 HTML 的 div 标签，而 <code>&lt;Welcome /&gt;</code> 则代表一个组件，并且需在作用域内使用 <code>Welcome</code>。</p>
</li>
<li><p>你可以在<a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized">深入 JSX</a> 中了解更多关于此规范的原因。</p>
</li>
</ul>
<h3 id="组合组件"><a href="#组合组件" class="headerlink" title="组合组件"></a>组合组件</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">function Welcome(props) &#123;</span><br><span class="line">  return &lt;h1&gt;Hello, &#123;props.name&#125;&lt;/h1&gt;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function App() &#123;</span><br><span class="line">  return (</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">      &lt;Welcome name=&quot;Sara&quot; /&gt;</span><br><span class="line">      &lt;Welcome name=&quot;Cahal&quot; /&gt;</span><br><span class="line">      &lt;Welcome name=&quot;Edite&quot; /&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;App /&gt;,</span><br><span class="line">  document.getElementById(&#x27;root&#x27;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<h3 id="Props的只读性"><a href="#Props的只读性" class="headerlink" title="Props的只读性"></a>Props的只读性</h3><p>​        <strong>所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。</strong></p>
<h2 id="State-amp-生命周期"><a href="#State-amp-生命周期" class="headerlink" title="State &amp; 生命周期"></a>State &amp; 生命周期</h2><h3 id="将函数组件转换为class组件"><a href="#将函数组件转换为class组件" class="headerlink" title="将函数组件转换为class组件"></a>将函数组件转换为class组件</h3><ul>
<li>创建同名class，继承于 React.Component</li>
<li>添加一个空的 render() 方法</li>
<li>将函数体移动到 render() 中</li>
<li>在render() 中，使用 this.props 替换 props</li>
<li>删除剩余的空函数声明。</li>
</ul>
<p>​        每次组件更新时 <code>render</code> 方法都会被调用，但只要在相同的 DOM 节点中渲染 <code>&lt;Clock /&gt;</code> ，就仅有一个 <code>Clock</code> 组件的 class 实例被创建使用。这就使得我们可以使用如 state 或生命周期方法等很多其他特性。</p>
<h3 id="向-class-组件中添加局部的-state"><a href="#向-class-组件中添加局部的-state" class="headerlink" title="向 class 组件中添加局部的 state"></a>向 class 组件中添加局部的 state</h3><ul>
<li><p>把 <code>render()</code> 方法中的 <code>this.props.date</code> 替换成 <code>this.state.date</code> ：</p>
</li>
<li><p>添加一个 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes#Constructor">class 构造函数</a>，然后在该函数中为 <code>this.state</code> 赋初值：</p>
</li>
<li><p>通过以下方式将 <code>props</code> 传递到父类的构造函数中：</p>
<ul>
<li>Class 组件应该始终使用 <code>props</code> 参数来调用父类的构造函数。</li>
</ul>
</li>
<li><p>移除 <code>&lt;Clock /&gt;</code> 元素中的 <code>date</code> 属性：</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">class Clock extends React.Component</span><br><span class="line">    &lt;any,</span><br><span class="line">        &#123;</span><br><span class="line">            date ?: any</span><br><span class="line">        &#125;&gt; &#123;</span><br><span class="line">    constructor(props: any) &#123;</span><br><span class="line">        super(props);</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            date: new Date()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;h1&gt;Hello&lt;/h1&gt;</span><br><span class="line">                &lt;h2&gt;it is &#123; this.state.date.toLocaleTimeString() &#125;&lt;/h2&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="生命周期方法添加到-Class-中"><a href="#生命周期方法添加到-Class-中" class="headerlink" title="生命周期方法添加到 Class 中"></a>生命周期方法添加到 Class 中</h3><ul>
<li>当 <code>Clock</code> 组件第一次被渲染到 DOM 中的时候，就为其<a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval">设置一个计时器</a>。这在 React 中被称为“挂载（mount）”。</li>
<li>同时，当 DOM 中 <code>Clock</code> 组件被删除的时候，应该<a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval">清除计时器</a>。这在 React 中被称为“卸载（unmount）”。</li>
</ul>
<h4 id="生命周期方法"><a href="#生命周期方法" class="headerlink" title="生命周期方法"></a>生命周期方法</h4><ul>
<li> <code>componentDidMount()</code> 方法会在组件已经被渲染到 DOM 中后运行</li>
<li> <code>componentWillUnmount()</code> 生命周期方法中清除</li>
</ul>
<h5 id="创建-clock-组件"><a href="#创建-clock-组件" class="headerlink" title="创建 clock 组件"></a>创建 clock 组件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">class Clock extends React.Component</span><br><span class="line">    &lt;</span><br><span class="line">        any,</span><br><span class="line">        &#123;</span><br><span class="line">            date : any</span><br><span class="line">        &#125;&gt; &#123;</span><br><span class="line">    private timerId: any;</span><br><span class="line">    constructor(props: any) &#123;</span><br><span class="line">        super(props);</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            date: new Date()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    componentDidMount() &#123;</span><br><span class="line">        this.timerId = setInterval(</span><br><span class="line">            () =&gt; this.tick(),</span><br><span class="line">            1000</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    componentWillUnmount() &#123;</span><br><span class="line">        clearInterval(this.timerId)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    tick() &#123;</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            date: new Date()</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;h1&gt;Hello&lt;/h1&gt;</span><br><span class="line">                &lt;h2&gt;it is &#123; this.state.date.toLocaleTimeString() &#125;&lt;/h2&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="调用顺序"><a href="#调用顺序" class="headerlink" title="调用顺序"></a>调用顺序</h5><ul>
<li>当 <code>&lt;Clock /&gt;</code> 被传给 <code>ReactDOM.render()</code>的时候，React 会调用 <code>Clock</code> 组件的构造函数。</li>
<li>之后 React 会调用组件的 <code>render()</code> 方法。</li>
<li>当 <code>Clock</code> 的输出被插入到 DOM 中后，React 就会调用 <code>ComponentDidMount()</code> 生命周期方法。</li>
<li>浏览器每秒都会调用一次 <code>tick()</code> 方法。 </li>
<li>一旦 <code>Clock</code> 组件从 DOM 中被移除，React 就会调用 <code>componentWillUnmount()</code> 生命周期方法。</li>
</ul>
<h3 id="正确的修改-State"><a href="#正确的修改-State" class="headerlink" title="正确的修改 State"></a>正确的修改 State</h3><h4 id="不要直接修改state里面的属性"><a href="#不要直接修改state里面的属性" class="headerlink" title="不要直接修改state里面的属性"></a>不要直接修改state里面的属性</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">// wrong, 这样写不会重新渲染组件。</span><br><span class="line">this.state.comm = &#x27;he&#x27;</span><br><span class="line"></span><br><span class="line">// correct</span><br><span class="line">this.setState(&#123;comm: &#x27;he&#x27;&#125;)</span><br></pre></td></tr></table></figure>

<p>​        构造函数是唯一可以给 <code>this.state</code> 赋值的地方。</p>
<h4 id="state更新可能是异步的"><a href="#state更新可能是异步的" class="headerlink" title="state更新可能是异步的"></a>state更新可能是异步的</h4><p>​        出于性能考虑，React 可能会把多个 <code>setState()</code> 调用合并成一个调用。</p>
<p>​        因为 <code>this.props</code> 和 <code>this.state</code> 可能会异步更新，所以你不要依赖他们的值来更新下一个状态。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">// Wrong</span><br><span class="line">例如，此代码可能会无法更新计数器：</span><br><span class="line">this.setState(&#123;</span><br><span class="line">  counter: this.state.counter + this.props.increment,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>​        要解决这个问题，可以让 <code>setState()</code> 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数，将此次更新被应用时的 props 做为第二个参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// Correct</span><br><span class="line">this.setState((state, props) =&gt; (&#123;</span><br><span class="line">  counter: state.counter + props.increment</span><br><span class="line">&#125;));</span><br></pre></td></tr></table></figure>

<h4 id="State-的更新会被合并"><a href="#State-的更新会被合并" class="headerlink" title="State 的更新会被合并"></a>State 的更新会被合并</h4><p>​        当你调用 <code>setState()</code> 的时候，React 会把你提供的对象合并到当前的 state。</p>
<p>​        这里的合并是浅合并，所以 <code>this.setState(&#123;comments&#125;)</code> 完整保留了 <code>this.state.posts</code>， 但是完全替换了 <code>this.state.comments</code>。</p>
<h3 id="数据是向下流动的"><a href="#数据是向下流动的" class="headerlink" title="数据是向下流动的"></a>数据是向下流动的</h3><p>​        组件可以选择把它的 state 作为 props 向下传递到它的子组件中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;FormattedDate date=&#123;this.state.date&#125; /&gt;</span><br></pre></td></tr></table></figure>

<p>​        <code>FormattedDate</code> 组件会在其 props 中接收参数 <code>date</code>，但是组件本身无法知道它是来自于 <code>Clock</code> 的 state，或是 <code>Clock</code> 的 props，还是手动输入的：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function FormattedDate(props) &#123;</span><br><span class="line">  return &lt;h2&gt;It is &#123;props.date.toLocaleTimeString()&#125;.&lt;/h2&gt;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="事件处理"><a href="#事件处理" class="headerlink" title="事件处理"></a>事件处理</h2><ul>
<li>React 事件的命名采用小驼峰式（camelCase），而不是纯小写。</li>
<li>使用 JSX 语法时你需要传入一个函数作为事件处理函数，而不是一个字符串。</li>
</ul>
<p>​        例如，传统的 HTML：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onclick=&quot;activateLasers()&quot;&gt;</span><br><span class="line">  Activate Lasers</span><br><span class="line">&lt;/button&gt;</span><br></pre></td></tr></table></figure>

<p>​        在 React 中略微不同：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onClick=&#123;activateLasers&#125;&gt;  Activate Lasers</span><br><span class="line">&lt;/button&gt;</span><br></pre></td></tr></table></figure>

<p>​        在 React 中另一个不同点是你不能通过返回 <code>false</code> 的方式阻止默认行为。你必须显式的使用 <code>preventDefault</code>。</p>
<p>​        在这里，<code>e</code> 是一个合成事件。React 根据 <a target="_blank" rel="noopener" href="https://www.w3.org/TR/DOM-Level-3-Events/">W3C 规范</a>来定义这些合成事件，所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。</p>
<p>​        但是，这样进行调用时，将无法使用 this，所以需要使用 bind 来进行绑定context上下文。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">正常的使用时。这里的this，因为是在onClick里面进行的调用，this将没有正确的指向。所以需要使用bind进行绑定。</span><br><span class="line">click(e ?: any) &#123;</span><br><span class="line">    console.log(this.props);</span><br><span class="line">    e.preventDefault()</span><br><span class="line">    console.log(&#x27;you are click&#x27;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">render() &#123;</span><br><span class="line">    return (</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;h1 onClick=&#123;this.click&#125;&gt;Hello&lt;/h1&gt;</span><br><span class="line">            &lt;h2&gt;it is &#123; this.state.date &#125;&lt;/h2&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">第一种，在constructor里面进行绑定this并返回</span><br><span class="line">constructor(props: any) &#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.state = &#123;</span><br><span class="line">        date: 1</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    this.click = this.click.bind(this)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">第二种，在onClick里面使用bind进行绑定上下文。</span><br><span class="line">render() &#123;</span><br><span class="line">    return (</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;h1 onClick=&#123;this.click.bind(this)&#125;&gt;Hello&lt;/h1&gt;</span><br><span class="line">            &lt;h2&gt;it is &#123; this.state.date &#125;&lt;/h2&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>如果不使用bind，可以使用两种方式。</p>
<p>​        如果你正在使用实验性的 <a target="_blank" rel="noopener" href="https://babeljs.io/docs/plugins/transform-class-properties/">public class fields 语法</a>，你可以使用 class fields 正确的绑定回调函数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// 此语法确保 `handleClick` 内的 `this` 已被绑定。</span><br><span class="line">// 注意: 这是 *实验性* 语法。</span><br><span class="line">// this。箭头函数来将this进行了定向指定。</span><br><span class="line">handleClick = () =&gt; &#123;</span><br><span class="line">  console.log(&#x27;this is:&#x27;, this);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        如果你没有使用 class fields 语法，你可以在回调中使用<a target="_blank" rel="noopener" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数</a>：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">render() &#123;</span><br><span class="line">  // 此语法确保 `handleClick` 内的 `this` 已被绑定。</span><br><span class="line">  return (</span><br><span class="line">    &lt;button onClick=&#123;() =&gt; this.handleClick()&#125;&gt;</span><br><span class="line">      Click me</span><br><span class="line">    &lt;/button&gt;</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        这个方式和上面是基本上是一样的。区别就是在于上面的语法是一个实验性语法。</p>
<h3 id="向事件处理程序传递参数"><a href="#向事件处理程序传递参数" class="headerlink" title="向事件处理程序传递参数"></a>向事件处理程序传递参数</h3><p>​        第一种，事件参数需要进行显式的传递</p>
<p>​        第二种，事件参数是使用的bind进行的绑定，所以会隐式的放在最后一个。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onClick=&#123;(e) =&gt; this.deleteRow(id, e)&#125;&gt;Delete Row&lt;/button&gt;</span><br><span class="line">&lt;button onClick=&#123;this.deleteRow.bind(this, id)&#125;&gt;Delete Row&lt;/button&gt;</span><br></pre></td></tr></table></figure>



<h2 id="条件渲染"><a href="#条件渲染" class="headerlink" title="条件渲染"></a>条件渲染</h2><p>​        React 中的条件渲染和 JavaScript 中的一样，使用 JavaScript 运算符 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else"><code>if</code></a> 或者<a target="_blank" rel="noopener" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">条件运算符</a>去创建元素来表现当前的状态，然后让 React 根据它们来更新 UI。</p>
<p>对于条件渲染我们可以使用几种方式：</p>
<ul>
<li><p>元素变量，使用if</p>
<ul>
<li>```<br>if () {<pre><code>&lt;LogoutButton onClick=&#123;this.handleLogoutClick&#125; /&gt;
</code></pre>
} else {<pre><code>&lt;LoginButton onClick=&#123;this.handleLoginClick&#125; /&gt;
</code></pre>
}<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 与运算符 &amp;&amp;， 注意，同时我们也可以知道，&#123;&#125; 里面如果是布尔类型，那么将不会生成dom，只有在属性里面attributes里面使用Boolean类型才会没有问题。</span><br><span class="line"></span><br><span class="line">  * ```</span><br><span class="line">    &#123; message &amp;&amp; &lt;h2&gt;</span><br><span class="line">              You have &#123;unreadMessages.length&#125; unread messages.</span><br><span class="line">            &lt;/h2&gt;&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>三目运算符</p>
<ul>
<li>```<br>The user is <b>{isLoggedIn ? ‘currently’ : ‘not’}</b> logged in.{isLoggedIn<pre><code>    ? &lt;LogoutButton onClick=&#123;this.handleLogoutClick&#125; /&gt;
    : &lt;LoginButton onClick=&#123;this.handleLoginClick&#125; /&gt;
  &#125;
</code></pre>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">    </span><br><span class="line"></span><br></pre></td></tr></table></figure>
function Greeting(props) {<br>const isLoggedIn = props.isLoggedIn;<br>if (isLoggedIn) {<br>return <UserGreeting>;<br>}<br>return <GuestGreeting>;<br>}</GuestGreeting></UserGreeting></li>
</ul>
</li>
</ul>
<p>ReactDOM.render(<br>  // Try changing to isLoggedIn={true}:<br>  <Greeting isloggedin="{false}">,<br>  document.getElementById(‘root’)<br>);</Greeting></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
<p>class Greeting extends React.Component&lt;any, any&gt; {<br>    constructor(props ?: any) {<br>        super(props);<br>    }</p>
<pre><code>render() &#123;
    return (
        this.props.loginState ?
            &lt;h1&gt;login&lt;/h1&gt; :
            &lt;h1&gt;logout&lt;/h1&gt;
    );
&#125;
</code></pre>
<p>}</p>
<p>class Clock extends React.Component&lt;any, {<br>    loginState ?: boolean<br>}&gt; {<br>    // private loginState: any;</p>
<pre><code>constructor(props ?: any) &#123;
    super(props);
    this.state = &#123;
        loginState: false,
    &#125;
&#125;

componentDidUpdate(prevProps: Readonly&lt;&#123;&#125;&gt;, prevState: Readonly&lt;&#123;&#125;&gt;, snapshot?: any) &#123;
    console.log(prevState)
&#125;

handleLoginClick() &#123;
    this.setState(&#123;
        loginState: true
    &#125;)
&#125;

handleLogoutClick() &#123;
    this.setState(&#123;
        loginState: false
    &#125;)
&#125;

render() &#123;
    let loginState = this.state.loginState
    let button = loginState ?
        &lt;button onClick=&#123;this.handleLogoutClick.bind(this)&#125;&gt;logout&lt;/button&gt; :
        &lt;button onClick=&#123;this.handleLoginClick.bind(this)&#125;&gt;login&lt;/button&gt;

    return (
        &lt;div&gt;
            &lt;Greeting loginState=&#123;loginState&#125;/&gt;
            &#123;button&#125;
        &lt;/div&gt;
    );
&#125;
</code></pre>
<p>}</p>
<p>ReactDOM.render(<br>    <Clock></Clock>,<br>    document.getElementById(‘root’)<br>)</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">### 阻止组件渲染</span><br><span class="line"></span><br><span class="line">​		可以通过render方法直接返回 null，来不进行渲染。</span><br><span class="line"></span><br><span class="line">​		在组件的 `render` 方法中返回 `null` 并不会影响组件的生命周期。例如，上面这个示例中，`componentDidUpdate` 依然会被调用。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## 列表 &amp; key</span><br><span class="line"></span><br><span class="line">### 渲染多个组件</span><br><span class="line"></span><br><span class="line">​		下面，我们使用 Javascript 中的 [`map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 方法来遍历 `numbers` 数组。将数组中的每个元素变成 `&lt;li&gt;` 标签，最后我们将得到的数组赋值给 `listItems`：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>const numbers = [1, 2, 3, 4, 5];<br>const listItems = numbers.map((number) =&gt;<br>  <li>{number}</li><br>);</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 基础列表组件</span><br><span class="line"></span><br><span class="line">​		当我们运行这段代码，将会看到一个警告 `a key should be provided for list items`，意思是当你创建一个元素时，必须包括一个特殊的 `key` 属性。我们将在下一节讨论这是为什么。</span><br><span class="line"></span><br><span class="line">​		key值用于diff算法的优化，Vue上面也有，所以不多赘述。</span><br><span class="line"></span><br><span class="line">​		我们这里只看一下 key 值是怎么进行使用的。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function NumberList(props) {<br>  const numbers = props.numbers;<br>  const listItems = numbers.map((number) =&gt;<br>    <li key="{number.toString()}"><br>      {number}<br>    </li><br>  );<br>  return (<br>    <ul>{listItems}</ul><br>  );<br>}</p>
<p>const numbers = [1, 2, 3, 4, 5];<br>ReactDOM.render(<br>  <NumberList numbers="{numbers}">,<br>  document.getElementById(‘root’)<br>);</NumberList></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### key</span><br><span class="line"></span><br><span class="line">​		key 帮助 React 识别哪些元素改变了，比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。</span><br><span class="line"></span><br><span class="line">​		写法：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>const numbers = [1, 2, 3, 4, 5];<br>const listItems = numbers.map((number) =&gt;<br>  <li key="{number.toString()}"><br>    {number}<br>  </li><br>);</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。</span><br><span class="line"></span><br><span class="line">​		当元素没有确定 id 的时候，万不得已你可以使用元素索引 index 作为 key。</span><br><span class="line"></span><br><span class="line">​		如果列表项目的顺序可能会变化，我们不建议使用索引来用作 key 值，因为这样做会导致性能变差，还可能引起组件状态的问题。可以看看 Robin Pokorny 的[深度解析使用索引作为 key 的负面影响](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318)这一篇文章。如果你选择不指定显式的 key 值，那么 React 将默认使用索引用作为列表项目的 key 值。</span><br><span class="line"></span><br><span class="line">​		要是你有兴趣了解更多的话，这里有一篇文章[深入解析为什么 key 是必须的](https://zh-hans.reactjs.org/docs/reconciliation.html#recursing-on-children)可以参考。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 用key提取组件</span><br><span class="line"></span><br><span class="line">​		元素的 key 只有放在就近的数组上下文中才有意义。</span><br><span class="line"></span><br><span class="line">​		比方说，如果你[提取](https://zh-hans.reactjs.org/docs/components-and-props.html#extracting-components)出一个 `ListItem` 组件，你应该把 key 保留在数组中的这个 `&lt;ListItem /&gt;` 元素上，而不是放在 `ListItem` 组件中的 `&lt;li&gt;` 元素上。</span><br><span class="line"></span><br><span class="line">​		简单来说，虽然listItem 里面就只有一个li，但是因为就近的数组上下文是使用的 listItem，所以我们就需要给listItem 来使用key，而不是把key写在li标签里面。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function ListItem(props) {<br>  const value = props.value;<br>  return (<br>    // 错误！你不需要在这里指定 key：<br>    <li key="{value.toString()}"><br>      {value}<br>    </li><br>  );<br>}</p>
<p>function NumberList(props) {<br>  const numbers = props.numbers;<br>  const listItems = numbers.map((number) =&gt;<br>    // 错误！元素的 key 应该在这里指定：<br>    <ListItem value="{number}"><br>  );<br>  return (<br>    <ul><br>      {listItems}<br>    </ul><br>  );<br>}</ListItem></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
<p>function ListItem(props) {<br>  // 正确！这里不需要指定 key：<br>  return <li>{props.value}</li>;<br>}</p>
<p>function NumberList(props) {<br>  const numbers = props.numbers;<br>  const listItems = numbers.map((number) =&gt;<br>    // 正确！key 应该在数组的上下文中被指定<br>    <ListItem key="{number.toString()}" value="{number}"><br>  );<br>  return (<br>    <ul><br>      {listItems}<br>    </ul><br>  );<br>}</ListItem></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		一个好的经验法则是：在 `map()` 方法中的元素需要设置 key 属性。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### key值在兄弟节点之间必须唯一</span><br><span class="line"></span><br><span class="line">​		数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而，它们不需要是全局唯一的。当我们生成两个不同的数组时，我们可以使用相同的 key 值。</span><br><span class="line"></span><br><span class="line">​		key 会传递信息给 React ，但不会传递给你的组件。如果你的组件中需要使用 `key` 属性的值，请用其他属性名显式传递这个值：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>const content = posts.map((post) =&gt;<br>  <Post key="{post.id}" id="{post.id}" title="{post.title}"><br>);</Post></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 在jsx中嵌套map()</span><br><span class="line"></span><br><span class="line">​		JSX 允许在大括号中[嵌入任何表达式](https://zh-hans.reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx)，所以我们可以内联 `map()` 返回的结果：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function NumberList(props) {<br>  const numbers = props.numbers;<br>  return (<br>    <ul><br>      {numbers.map((number) =&gt;<br>        <ListItem key="{number.toString()}" value="{number}"><br>      )}<br>    </ListItem></ul><br>  );<br>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## 表单</span><br><span class="line"></span><br><span class="line">### 受控组件</span><br><span class="line"></span><br><span class="line">​		在 HTML 中，表单元素（如`&lt;input&gt;`、 `&lt;textarea&gt;` 和 `&lt;select&gt;`）通常自己维护 state，并根据用户输入进行更新。而在 React 中，可变状态（mutable state）通常保存在组件的 state 属性中，并且只能通过使用 [`setState()`](https://zh-hans.reactjs.org/docs/react-component.html#setstate)来更新。</span><br><span class="line"></span><br><span class="line">​		我们可以把两者结合起来，使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<input type="text" value="{this.state.value}" onchange="{this.handleChange}">

<p>handleChange(event) {<br>    this.setState({value: event.target.value});<br>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		由于在表单元素上设置了 `value` 属性，因此显示的值将始终为 `this.state.value`，这使得 React 的 state 成为唯一数据源。由于 `handlechange` 在每次按键时都会执行并更新 React 的 state，因此显示的值将随着用户输入而更新。</span><br><span class="line"></span><br><span class="line">​		这里就是将value值给锁定了，然后使用了change方法来进行修改value，修改了state的value就会修改input的value，然后就会页面的修改。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<input type="text" value="{this.state.value}" onchange="{this.handleChange}">

<p>handleChange(event) {<br>  this.setState({value: event.target.value});<br>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		同时，我们也发现了，react的 onChange 事件，其实就是input事件。</span><br><span class="line"></span><br><span class="line">​		同时 text area 文本输入框，也是一样的使用 value 来进行值的操作。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#### select 标签</span><br><span class="line"></span><br><span class="line">​		React 并不会使用 `selected` 属性，而是在根 `select` 标签上使用 `value` 属性。这在受控组件中更便捷，因为您只需要在根标签中更新它。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<select value="{this.state.value}" onchange="{this.handleChange}">
    <option value="grapefruit">葡萄柚</option>
    <option value="lime">酸橙</option>
    <option value="coconut">椰子</option>
    <option value="mango">芒果</option>
</select>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		通过value属性的变化，来确定selected的显示。</span><br><span class="line"></span><br><span class="line">&gt; 注意</span><br><span class="line">&gt;</span><br><span class="line">&gt; 你可以将数组传递到 `value` 属性中，以支持在 `select` 标签中选择多个选项：</span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure>
> <select multiple="{true}" value="{['B'," 'c']}>
> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#### 文件 input 标签</span><br><span class="line"></span><br><span class="line">​		在 HTML 中，`&lt;input type=&quot;file&quot;&gt;` 允许用户从存储设备中选择一个或多个文件，将其上传到服务器，或通过使用 JavaScript 的 [File API](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications) 进行控制。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</select><input type="file">
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		因为它的 value 只读，所以它是 React 中的一个**非受控**组件。将与其他非受控组件[在后续文档中](https://zh-hans.reactjs.org/docs/uncontrolled-components.html#the-file-input-tag)一起讨论。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 处理多个输入</span><br><span class="line"></span><br><span class="line">​		当需要处理多个 `input` 元素时，我们可以给每个元素添加 `name` 属性，并让处理函数根据 `event.target.name` 的值选择要执行的操作。</span><br><span class="line"></span><br><span class="line">​		我开始的方法是，通过传递一个参数，来代表是哪个input输入，然后再进行一个处理判断。</span><br><span class="line"></span><br><span class="line">​		这里记住，这个value是不能接收Boolean类型的。但是checked可以。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
通过传递参数来判断是哪个输入。然后再在handleInputChange事件里面进行判断处理

<p>&lt;input type=”number” id={‘input’} onChange={(e) =&gt; this.handleInputChange(e, ‘input’)} value={this.state.numberOfGuests}/&gt;</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		我们通过设置input的name，然后通过type来获取不同的值，并且通过name来进行赋值给state。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>handleInputChange(event) {<br>    const target = event.target;<br>    const value = target.type === ‘checkbox’ ? target.checked : target.value;<br>    const name = target.name;</p>
<pre><code>this.setState(&#123;
    [name]: value
&#125;);
</code></pre>
<p>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		这里使用了 ES6 [计算属性名称](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names)的语法更新给定输入名称对应的 state 值。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>interface IAddPlayerFormState {<br>    isGoing: boolean,<br>    numberOfGuests: number<br>}</p>
<p>handleInputChange(event ?: any) {<br>    const target = event.target<br>    const value = target.type===’checkbox’ ? target.checked : target.value<br>    const name = target.name</p>
<pre><code>this.setState(&#123;
    [name]: value
&#125; as Pick&lt;IAddPlayerFormState, keyof IAddPlayerFormState&gt;)
</code></pre>
<p>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 受控输入空值</span><br><span class="line"></span><br><span class="line">​		在[受控组件](https://zh-hans.reactjs.org/docs/forms.html#controlled-components)上指定 `value` 的 prop 会阻止用户更改输入。如果你指定了 `value`，但输入仍可编辑，则可能是你意外地将 `value` 设置为 `undefined` 或 `null`。</span><br><span class="line"></span><br><span class="line">​		下面的代码演示了这一点。（输入最初被锁定，但在短时间延迟后变为可编辑。）</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>ReactDOM.render(<input value="hi">, mountNode);</p>
<p>setTimeout(function() {<br>  ReactDOM.render(<input value="{null}">, mountNode);<br>}, 1000);</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 受控组件的替代品</span><br><span class="line"></span><br><span class="line">​		有时使用受控组件会很麻烦，因为你需要为数据变化的每种方式都编写事件处理函数，并通过一个 React 组件传递所有的输入 state。当你将之前的代码库转换为 React 或将 React 应用程序与非 React 库集成时，这可能会令人厌烦。在这些情况下，你可能希望使用[非受控组件](https://zh-hans.reactjs.org/docs/uncontrolled-components.html), 这是实现输入表单的另一种方式。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## 状态提升</span><br><span class="line"></span><br><span class="line">​		状态提升，其实简单来说就是子组件可以修改数据传递给父组件。</span><br><span class="line"></span><br><span class="line">​		方法其实也是和vue的差不多。vue子组件可以通过 $emit 通知父组件进行方法的调用。而react是通过直接调用父组件传递过来的方法进行调用。this.props.onTemperatureChange(event.target.value) 这个方法就是父组件传递过来的方法。父组件的attributes 属性。onTemperatureChange=&#123;this.handleCelsiusChange&#125;。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>const scaleNames : ScaleState = {<br>    c: ‘Celsius’,<br>    f: ‘Fahrenheit’<br>}</p>
<p>interface ScaleState {<br>    [key : string]: string<br>}<br>interface valueState {<br>    scale ?: string,<br>    temperature : number,<br>}</p>
<p>class TemperatureInput extends React.Component&lt;any, valueState&gt; {<br>    constructor(props?:any) {<br>        super(props);</p>
<pre><code>    this.state = &#123;
        temperature: 0
    &#125;

    this.handleChange = this.handleChange.bind(this)
&#125;

handleChange(event : any) &#123;
    // this.setState(&#123;
    //     temperature: event.target.value
    // &#125;)
    this.props.onTemperatureChange(event.target.value)
&#125;

render() &#123;
    const temperature = this.props.temperature
    const scale = this.props.scale
    return (
        &lt;fieldset&gt;
            &lt;legend&gt;Enter temperature in &#123;scaleNames[scale]&#125;: &lt;/legend&gt;
            &lt;input
                type=&quot;text&quot;
                value=&#123;temperature&#125;
                onChange=&#123;this.handleChange&#125; /&gt;
        &lt;/fieldset&gt;
    );
&#125;
</code></pre>
<p>}</p>
<p>interface valueStateCalculator {<br>    temperature: string,<br>    scale: string<br>}<br>class Calculator extends React.Component&lt;any, valueStateCalculator&gt; {<br>    constructor(props ?: any) {<br>        super(props);</p>
<pre><code>    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this)
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this)

    this.state = &#123;temperature: &#39;&#39;, scale: &#39;c&#39;&#125;;
&#125;

handleCelsiusChange(temperature : string) &#123;
    this.setState(&#123;
        scale: &#39;c&#39;,
        temperature
    &#125;)
&#125;
handleFahrenheitChange(temperature : string) &#123;
    this.setState(&#123;
        scale: &#39;f&#39;,
        temperature
    &#125;);
&#125;

toCelsius(fahrenheit : number) &#123;
    return (fahrenheit - 32) * 5 / 9;
&#125;
toFahrenheit(celsius : number) &#123;
    return (celsius * 9 / 5) + 32;
&#125;
tryConvert(temperature:string, convert:Function) &#123;
    const input = parseFloat(temperature);
    if (Number.isNaN(input)) &#123;
        return &#39;&#39;;
    &#125;
    const output = convert(input);
    const rounded = Math.round(output * 1000) / 1000;
    return rounded.toString();
&#125;

render() &#123;
    const scale = this.state.scale
    const temperature = this.state.temperature
    const celsius = scale===&#39;f&#39; ?
        this.tryConvert(temperature, this.toCelsius) :
        temperature;
    const fahrenheit  = scale===&#39;c&#39; ?
        this.tryConvert(temperature, this.toFahrenheit) :
        temperature;

    return (
        &lt;div&gt;
            &lt;TemperatureInput
                scale=&#123;&#39;c&#39;&#125;
                temperature=&#123;celsius&#125;
                onTemperatureChange=&#123;this.handleCelsiusChange&#125;&gt;&lt;/TemperatureInput&gt;
            &lt;TemperatureInput
                scale=&#123;&#39;f&#39;&#125;
                temperature=&#123;fahrenheit&#125;
                onTemperatureChange=&#123;this.handleFahrenheitChange&#125;&gt;&lt;/TemperatureInput&gt;
        &lt;/div&gt;
    );
&#125;
</code></pre>
<p>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## 组合 vs 继承</span><br><span class="line"></span><br><span class="line">### 包含关系</span><br><span class="line"></span><br><span class="line">​		有些组件无法提前知晓它们子组件的具体内容。在 `Sidebar`（侧边栏）和 `Dialog`（对话框）等展现通用容器（box）的组件中特别容易遇到这种情况。</span><br><span class="line"></span><br><span class="line">​		我们建议这些组件使用一个特殊的 `children` prop 来将他们的子组件传递到渲染结果中：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function FancyBorder(props) {<br>  return (<br>    &lt;div className={‘FancyBorder FancyBorder-‘ + props.color}&gt;<br>      {props.children}<br>    <br>  );<br>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
<p>function WelcomeDialog() {<br>  return (<br>    <FancyBorder color="blue"><br>      <h1 classname="Dialog-title"><br>        Welcome<br>      </h1><br>      <p classname="Dialog-message"><br>        Thank you for visiting our spacecraft!<br>      </p><br>    </FancyBorder><br>  );<br>}</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		这个就类似于vue组件的插槽式写法。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">​		命名props传递</span><br><span class="line"></span><br><span class="line">​		具名插槽，写法和vue不同</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function SplitPane(props) {<br>  return (<br>    <div classname="SplitPane"><br>      <div classname="SplitPane-left"><br>        {props.left}<br>      </div><br>      <div classname="SplitPane-right"><br>        {props.right}<br>      </div><br>    </div><br>  );<br>}</p>
<p>function App() {<br>  return (<br>    &lt;SplitPane<br>      left={<br>        <Contacts><br>      }<br>      right={<br>        <Chat><br>      } /&gt;<br>  );<br>}</Chat></Contacts></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		定义时，通过直接调用 props.left 来进行调用，注意，这个插槽和props属性是共通的。所以其实对于react来说，并没有分插槽这个属性。reac内部会使用。自己的方法进行处理。不用我们进行操作。</span><br><span class="line"></span><br><span class="line">​		同时 react的 ‘具名插槽‘ 的使用形式是直接在组件里面进行调用，但是传值需要在属性里面进行传值，所以这就是说为什么react没有插槽这一概念的原因。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 特例关系</span><br><span class="line"></span><br><span class="line">​		在 React 中，我们也可以通过组合来实现这一点。“特殊”组件可以通过 props 定制并渲染“一般”组件：</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>function Dialog(props) {<br>  return (<br>    <FancyBorder color="blue"><br>      <h1 classname="Dialog-title"><br>        {props.title}<br>      </h1><br>      <p classname="Dialog-message"><br>        {props.message}<br>      </p><br>    </FancyBorder><br>  );<br>}</p>
<p>function WelcomeDialog() {<br>  return (<br>    <Dialog title="Welcome" message="Thank you for visiting our spacecraft!"><br>  );<br>}</Dialog></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		简单来说就是显示是通过props的内容进行的显示，同时传递时通过传递这个对应的内容，让页面进行渲染。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">​		Props 和组合为你提供了清晰而安全地定制组件外观和行为的灵活方式。注意：组件可以接受任意 props，包括基本数据类型，React 元素以及函数。</span><br><span class="line"></span><br><span class="line">​		如果你想要在组件间复用非 UI 的功能，我们建议将其提取为一个单独的 JavaScript 模块，如函数、对象或者类。组件可以直接引入（import）而无需通过 extend 继承它们。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## react哲学</span><br><span class="line"></span><br><span class="line">### 第一步：将设计好的 UI 划分为组件层级</span><br><span class="line"></span><br><span class="line">​		划分组件，分层。抽离组件。</span><br><span class="line"></span><br><span class="line">### 第二步：用 React 创建一个静态版本</span><br><span class="line"></span><br><span class="line">### 第三步：确定 UI state 的最小（且完整）表示</span><br><span class="line"></span><br><span class="line">通过问自己以下三个问题，你可以逐个检查相应数据是否属于 state：</span><br><span class="line"></span><br><span class="line">1. 该数据是否是**由父组件通过 props 传递而来**的？如果是，那它应该不是 state。</span><br><span class="line">2. 该数据**是否随时间的推移而保持不变**？如果是，那它应该也不是 state。</span><br><span class="line">3. 你**能否根据其他 state 或 props 计算出该数据的值**？如果是，那它也不是 state。</span><br><span class="line"></span><br><span class="line">### 第四步：确定 state 放置的位置</span><br><span class="line"></span><br><span class="line">对于应用中的每一个 state：</span><br><span class="line"></span><br><span class="line">- 找到根据这个 state 进行渲染的所有组件。</span><br><span class="line">- 找到他们的共同所有者（common owner）组件（在组件层级上高于所有需要该 state 的组件）。</span><br><span class="line">- 该共同所有者组件或者比它层级更高的组件应该拥有该 state。</span><br><span class="line">- 如果你找不到一个合适的位置来存放该 state，就可以直接创建一个新的组件来存放该 state，并将这一新组件置于高于共同所有者组件层级的位置</span><br><span class="line"></span><br><span class="line">### 第五步：添加反向数据流</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">​		先继承 react.component 组件的内容，然后再在在自己的方法里面添加一个render 方法。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>class ShoppingList extends React.Component {<br>  render() {<br>    return (<br>      <div classname="shopping-list"><br>        <h1>Shopping List for {this.props.name}</h1><br>        <ul><br>          <li>Instagram</li><br>          <li>WhatsApp</li><br>          <li>Oculus</li><br>        </ul><br>      </div><br>    );<br>  }<br>}</p>
<p>// 用法示例: <ShoppingList name="Mark"></ShoppingList></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		上述代码等同于:</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>return React.createElement(‘div’, {className: ‘shopping-list’},<br>  React.createElement(‘h1’, /* … h1 children … <em>/),<br>  React.createElement(‘ul’, /</em> … ul children … */)<br>);</p>
<pre><code>
</code></pre>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/React/" rel="tag"># React</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/2022/02/12/JavaScript/%E9%9A%8F%E7%AC%94/if%20in%20%E7%94%A8%E6%B3%95/" rel="prev" title="if in 用法">
                  <i class="fa fa-chevron-left"></i> if in 用法
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/2022/02/15/JavaScript/JavaScript-%E7%B1%BB/" rel="next" title="JavaScript-类">
                  JavaScript-类 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">tallgy</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  





  





</body>
</html>
